#pragma once

#include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <random>
#include <iomanip>
#include <atomic>

#include <jsoncpp/json/json.h>

#include "log.hpp"

namespace JsonRpc
{
    class JSON
    {
    public:
        static bool Serialize(const Json::Value &val, std::string &body)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

            std::stringstream ss;
            int ret = sw->write(val, &ss);
            if (ret != 0)
            {
                LOG(ERROR, "json serialize failed\n");
                //std::cout << "json serialize failed" << std::endl;
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool Deserialize(const std::string &body, Json::Value &val)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

            std::string err;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &err);
            if (ret == false)
            {
                LOG(ERROR, "json deserialize failed : %s\n", err.c_str());
                //std::cout << "json deserialize failed :" << err << std::endl;
            }

            return ret;
        }
    };

    class UUID
    {
    public:
        static std::string uuid()
        {
            std::stringstream ss;
            // 构造一个机器随机数对象
            std::random_device rd;
            // 以机器随机数为种子构建一个伪随机对象
            std::mt19937 genertor(rd());
            // 限制随机数生成大小
            std::uniform_int_distribution<int> distribution(0, 255);
            // 生成8个随机数，按照特定格式组织成16进制的数字字符串
            for (int i = 0; i < 8; ++i)
            {
                if (i == 4 || i == 6)
                    ss << "-";

                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(genertor);
            }
            ss << "-";

            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);

            // 定义一个8字节序号，逐字节组成16进制的数字字符串
            for (int i = 7; i >= 0; --i)
            {
                if (i == 5)
                    ss << "-";
                
                ss << std::setw(2) << std::setfill('0') << std::hex << (cur >> (i * 8) & 0xFF);
            }

            return ss.str();
        }
    };

}